package com.bicon.botu.mall.coupon.service.impl;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.core.base.common.utils.JsonUtil;
import com.bicon.botu.core.base.common.utils.StringUtils;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.mall.coupon.common.CouponStatus;
import com.bicon.botu.mall.coupon.dto.CouponsPageDto;
import com.bicon.botu.mall.coupon.entity.Coupons;
import com.bicon.botu.mall.coupon.mapper.CouponsMapper;
import com.bicon.botu.mall.coupon.service.ICouponsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 优惠券实体类 服务实现类
 * </p>
 *
 * @author 吕祥
 * @since 2017-07-19
 */
@Slf4j
@Service
public class CouponsServiceImpl extends ServiceImpl<CouponsMapper, Coupons> implements ICouponsService {

    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private CouponsMapper couponsMapper;

    /**
     * 新增 优惠券
     *
     * @param name           活动名称
     * @param discountAmount 优惠金额
     * @param orderAmount    订单最小金额
     * @param number         优惠券数量
     * @param firsDate       开始使用日期
     * @param lastDate       最后使用日期
     * @param issueDate      优惠券发行日期
     * @param endingDate     优惠券发行结束日期
     * @param path           优惠券使用范围
     * @param remarks        备注
     * @param shopName       商家名称
     * @param issueState     发行状态
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult add(String name, String discountAmount, String orderAmount,
                          Integer number, String firsDate, String lastDate, String issueDate,
                          String endingDate, String path, String remarks, String shopName, Integer type, int issueState) {
        Coupons coupons = new Coupons();
        coupons.setName(name);
        coupons.setDiscountAmount(new BigDecimal(discountAmount));
        coupons.setOrderAmount(new BigDecimal(orderAmount));
        coupons.setNumber(number);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = dateFormat.parse(firsDate);
            coupons.setFirsDate(date);

            date = dateFormat.parse(lastDate);
            coupons.setLastDate(date);

            date = dateFormat.parse(issueDate);
            coupons.setIssueDate(date);

            date = dateFormat.parse(endingDate);
            coupons.setEndingDate(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        coupons.setPath(path);
        coupons.setRemarks(remarks);
        coupons.setShopName(shopName);
        coupons.setType(type);
        coupons.setIssueState(issueState);
        coupons.preInsert();
        boolean result = coupons.insert();
        if (result) {
            //redis Key
            String redisKey = CouponStatus.BOTU + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.MALL + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPON + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPONS;
            redisHandler.getLocalRedisTemplate().cacheHash(redisKey, "", coupons.getId(), JsonUtil.toJson(coupons));
            return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
        } else {
            return new BaseResult(CouponStatus.RESPONSE_CODE_500, CouponStatus.RESPONSE_MESSAGE_500);
        }
    }

    /**
     * 修改优惠券
     *
     * @param id             优惠券id
     * @param name           活动名称
     * @param discountAmount 优惠金额
     * @param orderAmount    订单最小金额
     * @param number         优惠券数量
     * @param firsDate       开始使用日期
     * @param lastDate       最后使用日期
     * @param issueDate      优惠券发行日期
     * @param endingDate     优惠券发行结束日期
     * @param path           优惠券使用范围
     * @param remarks        备注
     * @param shopName       商家名称
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult updateById(String id, String name, String discountAmount, String orderAmount,
                                 Integer number, String firsDate, String lastDate, String issueDate,
                                 String endingDate, String path, String remarks, String shopName, Integer type) {
        Coupons coupons = new Coupons().selectById(id);
        if (null == coupons) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_602, CouponStatus.RESPONSE_MESSAGE_602);
        }
        if (null != name) {
            coupons.setName(name);
        }
        if (null != discountAmount) {
            coupons.setDiscountAmount(new BigDecimal(discountAmount));
        }
        if (null != orderAmount) {
            coupons.setOrderAmount(new BigDecimal(orderAmount));
        }
        if (null != String.valueOf(number)) {
            coupons.setNumber(number);
        }
        Date date = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            if (null != firsDate) {
                date = dateFormat.parse(firsDate);
                coupons.setFirsDate(date);
            }
            if (null != lastDate) {
                date = dateFormat.parse(lastDate);
                coupons.setLastDate(date);
            }
            if (null != issueDate) {
                date = dateFormat.parse(issueDate);
                coupons.setIssueDate(date);
            }
            if (null != endingDate) {
                date = dateFormat.parse(endingDate);
                coupons.setEndingDate(date);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != path) {
            coupons.setPath(path);
        }
        if (null != remarks) {
            coupons.setRemarks(remarks);
        }
        if (null != shopName) {
            coupons.setShopName(shopName);
        }
        if (null != type) {
            coupons.setType(type);
        }
        coupons.preUpdate();
        boolean result = coupons.updateById();
        return getBaseResult(coupons, result);
    }

    /**
     * 缓存更新
     *
     * @param coupons   优惠券
     * @param result    是否执行
     * @return
     */
    private BaseResult getBaseResult(Coupons coupons, boolean result) {
        if (result) {
            //redis Key
            String redisKey = CouponStatus.BOTU + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.MALL + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPON + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPONS;
            redisHandler.getLocalRedisTemplate().cacheHash(redisKey, "", coupons.getId(), JsonUtil.toJson(coupons));
            return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
        } else {
            return new BaseResult(CouponStatus.RESPONSE_CODE_600, CouponStatus.RESPONSE_MESSAGE_600);
        }
    }

    /**
     * 批量删除优惠券
     *
     * @param idJson 优惠券id集合(Json格式参数)
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteById(String idJson) {
        if (!StringUtils.isNotBlank(idJson)) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_400, CouponStatus.RESPONSE_MESSAGE_400);
        }
        List<String> idList = JsonUtil.fromJson(idJson, ArrayList.class);
        if (idList.size() <= 0) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_400, CouponStatus.RESPONSE_MESSAGE_400);
        }
        for (String id : idList) {
            Coupons entity = new Coupons().selectOne(new EntityWrapper<Coupons>().eq("id", id).eq("logic_delete", CouponStatus.DEL_LOGIC_NORMAL));
            if (null == entity) {
                continue;
            }
            Date nowDate = new Date();
            Date endingDate = entity.getEndingDate();
            Date issueDate = entity.getIssueDate();
            if (nowDate.getTime() < endingDate.getTime() && nowDate.getTime() > issueDate.getTime()) {
                return new BaseResult(CouponStatus.RESPONSE_CODE_600, "还在使用期不可删除~!");
            }
            entity.preDelete();
            boolean result = entity.updateById();
            if (result) {
                //redis Key
                String redisKey = CouponStatus.BOTU + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.MALL + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPON + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPONS;
                redisHandler.getLocalRedisTemplate().removeHash(redisKey, "", entity.getId());
            } else {
                return new BaseResult(CouponStatus.RESPONSE_CODE_600, CouponStatus.RESPONSE_MESSAGE_600);
            }
        }

        return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
    }

    /**
     * 发行
     *
     * @param id         优惠券id
     * @param issueState 发行状态
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult issue(String id, int issueState) {
        Coupons coupons = new Coupons().selectById(id);
        coupons.setIssueState(issueState);
        coupons.preUpdate();
        boolean result = coupons.updateById();
        return getBaseResult(coupons, result);
    }

    /**
     * 优惠券分页查询
     *
     * @param pageNo   页面数
     * @param pageSize 每页大小
     * @param name     活动名称
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Page<CouponsPageDto> page(int pageNo, int pageSize, String name) {
        Map<String, String> map = new HashMap<String, String>(2);
        map.put("name", name);
        Page<CouponsPageDto> page = new Page<CouponsPageDto>(pageNo, pageSize);
        List<CouponsPageDto> couponsPageDtos = couponsMapper.findPage(page, map);
        List<String> couponsIds = new ArrayList<>();
        couponsPageDtos.stream().forEach(dto -> {
            if (String.valueOf(CouponStatus.IN_CIRCULATION).equals(dto.getIssueState()) && CouponStatus.ISSUED_PERIOD.equals(dto.getState())) {
                dto.setIssueState(String.valueOf(CouponStatus.STOPPAGE_OF_PUBLICATION));
                couponsIds.add(dto.getId());
            }
        });
        if (CollectionUtils.isNotEmpty(couponsIds)) {
            List<Coupons> couponsList = new Coupons().selectList(new EntityWrapper<Coupons>().in("id", couponsIds));
            couponsList.stream().forEach(entity -> {
                entity.setIssueState(CouponStatus.STOPPAGE_OF_PUBLICATION);
                entity.preUpdate();
                getBaseResult(entity, true);
            });
            this.updateBatchById(couponsList);
        }
        page.setRecords(couponsPageDtos);
        return page;
    }

    /**
     * 查询所有在发行期内的优惠券
     *
     * @return 所有在发行期内的优惠券
     */
    @Override
    public List<Coupons> findAllRedis() {
        //redis Key
        String redisKey = CouponStatus.BOTU + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.MALL + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPON + CouponStatus.REDIS_KEY_DELIMITER + CouponStatus.COUPONS;
        Map<Object, Object> map = redisHandler.getLocalRedisTemplate().getHashMap(redisKey, "");
        //保存缓存取出的所有对象
        List<Coupons> couponsList = new ArrayList<Coupons>();
        for (Object obj : map.values()) {
            Coupons coupons = JsonUtil.fromJson(String.valueOf(obj), Coupons.class);
            couponsList.add(coupons);
        }
        //保存符合条件的对象 并返回数据  (在发行时间内的优惠券)
        List<Coupons> resultList = new ArrayList<Coupons>();
        for (Coupons entity : couponsList) {
            Date dateIssue = entity.getIssueDate();
            Date dateEnding = entity.getEndingDate();
            Date dateNow = new Date();
            if (entity.getIssueState() == CouponStatus.IN_CIRCULATION) {
                if (dateNow.getTime() > dateIssue.getTime() && dateNow.getTime() < dateEnding.getTime()) {
                    resultList.add(entity);
                }
            }
        }
        if (resultList.size() > 0 && null != resultList) {
            return resultList;
        } else {
            return null;
        }
    }
}
